const http = require('http');
const urlParser = require('url');

const server = http.createServer(/*(req,res) => {

}*/);

//这里注册的回调等同于直接在http.createServer接受的回调
server.on("request", (req,res) => {
  /*req 是一个可读流 on('data')
    1.method 请求的方法
    2.url 请求的路径
    3.headers 请求头对象
    4.httpVersion 客户端的http版本
    5.socket 监听客户端请求的socket对象
  */
  //res 是一个可写流 write end
  console.log("welcome");
  const method = req.method; // 大写的
  let url = req.url; // 完整的请求路径 从端口号之后 到#(hash)之前
  const version = req.httpVersion;
  console.log(method, url, version);
  //← http://localhost:8080/123?a=1&b=2
  //→ GET /123?a=1&b=2 1.1

  //拿到的url长这样 /123?a=1&b=2
  //我们可以用url模块对此进行解析

  url = urlParser.parse(url, true); //置为true 会将query转化为对象
  console.log('url:',url);

  console.log('req.headers:',req.headers); // 我们这里接受到的请求头的key都是小写的

  const arr = [];
  //获取请求体
  req.on('data', data => {
    console.log('data');
    arr.push(data);
  });

  //post请求获取完请求体会走这个
  // ，或则是get请求(会直接在req自定义可读流中push(null)，也就会触发end事件)
  req.on('end', data => {
    console.log('end');
    console.log(Buffer.concat(arr).toString()); //不一定要toString() 比如上传了一个图片撒的
  });



  // ------ 响应相关的 ------
  res.statusCode = 404; //node会帮我们自动补上原因短语 当然如果你手动设置了的话会覆盖
  res.setHeader("a", 1); //需先设置头 再写，这里就是在Response Headers里添加了一对键值对 a: 1
  // res.setHeader("Content-Type", "text/plain;charset=utf-8"); //Content-Type对照表，不填这个你返回的信息有中文的话是会乱码的

  //res.writeHead(statusCode[, statusMessage][, headers])
  //res.removeHeader('Content-Type');
  //res.headersSent //判断响应头是否已经发送
  //
  //res.sendDate = false; //不发送Date
  //res.getHeader(name) //读出已排队但未发送到客户端的响应头。 该名称不区分大小写。 返回值的类型取决于提供给 response.setHeader() 的参数。
  // res.setTimeout(msecs,[callback]);  //可以使用setTimeout方法设置响应让超时时间，如果在指定时间内不响应，则触发timeout事件
  // res.on('timeout',callback);

  //在响应对象的end方法被调用之前，如果连接中断，将触发http.ServerResponse对象的close事件
  // res.on('close',callback);


  //重定向
  // res.redirect('http://itbilu.com/');
  // res.redirect('http://itbilu.com/',301);
  // res.writeHead(301, {'Location': 'http://itbilu.com/'});

  res.write("hello,");
  res.end("世界!"); //end不调用响应不结束
});

let port = 8080;
server.listen(port/*,hostname:默认就是本机*//*,backlog:指定位于等待队列中的客户端连接数*/, () => {
  console.log("server start at " + port);
});

//如果端口号已经被监听 则端口号累加 再试
server.on('error',function(err){
  if(err.code === 'EADDRINUSE'){
    server.listen(++port); //← 不用重复传回调，上面的listeningListener仍然会执行
  }
});


// server.close();//关闭服务器

/*server.on('connection', () => {
  console.log('客户端已建立连接');
});*/





//设置超时时间
/*server.setTimeout(120000/!*默认值: 120000（2 分钟）*!/, () => {
/!*
设置套接字的超时值，并在服务器对象上触发 'timeout' 事件，如果发生超时，则将套接字作为参数传入。

如果服务器对象上有 'timeout' 事件监听器，则将使用超时的套接字作为参数调用它。

默认情况下，服务器的超时值为 2 分钟，如果超时，套接字会自动销毁。 但是，如果将回调分配给服务器的 'timeout' 事件，则必须显式处理超时。

若要更改默认的超时，请使用 --http-server-default-timeout 标志。
*!/
});
//等同↑的回调
server.on('timeout',()=>{
  '连接已超时'
})*/














/* 自动重启服务器
npm i nodemon -g
nodemon 01.http-server.js
*/





//关于url
// const url = require('url');
// console.log(url.parse('http://localhost:3000/abc?name=%E5%A4%A7%E9%BB%84&age=11'));
/*
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'localhost:3000',
  port: '3000',
  hostname: 'localhost',
  hash: null,
  search: '?name=%E5%A4%A7%E9%BB%84&age=11',
  query: 'name=%E5%A4%A7%E9%BB%84&age=11',
  pathname: '/abc',
  path: '/abc?name=%E5%A4%A7%E9%BB%84&age=11',
  href: 'http://localhost:3000/abc?name=%E5%A4%A7%E9%BB%84&age=11' }
*/